#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
主题: 执行精确的浮点数运算
问题: 你需要对浮点数执行精确的计算操作，并且不希望有任何小误差的出现。
提示 : 
    1. 普通浮点数能提供的17位精度
"""

from decimal import Decimal
from decimal import localcontext

def recipe1():
    """底层CPU和IEEE 754标准通过自己的浮点单位去执行算术时的特征"""
    a = 4.2
    b = 2.1
    print(f"{a = }")
    print(f"{b = }")
    print(f"{a + b = }")
    print(f"{a + b == 6.3 = }")

def recipe2():
    """使用 decimal 模块"""
    a = Decimal('4.2')
    b = Decimal('2.1')
    print(f"{a = }")
    print(f"{b = }")
    print(f"{a + b = }")
    print(f"{a + b == Decimal(6.3) = }")

def recipe3():
    """控制计算的每一方面，包括数字位数和四舍五入运算"""
    a = Decimal('1.3')
    b = Decimal('1.7')
    print(f"{a = }")
    print(f"{b = }")
    print(f"{a / b = }")
    
    with localcontext() as ctx:
        ctx.prec = 3
        print(f"{a / b = }")

    with localcontext() as ctx:
        ctx.prec = 50
        print(f"{a / b = }")

def recipe4():
    """注意下减法删除以及大数和小数的加分运算所带来的影响"""
    nums = [1.23e+16, 1, -1.23e+16]
    print(f"{nums = }")
    print(f"{sum(nums) = }") # 注意结果是0， 将指数改为15时结果正常

    import math
    print(f"{math.fsum(nums) = }")

def main():
    print('recipe1'.center(20, '*'))
    recipe1() 
    print('recipe2'.center(20, '*'))
    recipe2() 
    print('recipe3'.center(20, '*'))
    recipe3()    
    print('recipe4'.center(20, '*'))
    recipe4() 

if __name__ == '__main__':
    main()         